今天將直接實作 redux,如果不知道 redux 運作概念的讀者可以回去看看昨天的概念介紹喔~
今天嘗試將 dark theme 與 light theme 實作出來,將決定 dark 還是 light 的 state 放在 store 中,讓 component 都可以去 store 抓取,並透過 button 做背景模式的切換。
首先先在專案的 root 創建 actions、reducers、store 三個資料夾,分別存放 redux 三大元素的程式碼,當然你也可以把他們寫在一起,但考慮到專案如果擴大,維護上會很困難,因此還是養成切分檔案的習慣吧!
接著從 action 開始著手吧!
actions 資料夾中 建立 themeAction.js,並輸入:
export const changeTheme = () => {
return {
type: 'CHANGE_THEME'
}
}
這邊使用到 action creator 的概念,將 action 用函式包裝起來,這樣在 dispatch 中只要呼叫這個函式就可以了。因為這次實作的內容比較簡單,我們只需要對 global state 做 true and false 的切換,因此 action 中只需要帶上 type 就好,不需要帶 payload ,也只需要一個 action 就夠了。
接著在 reducers 資料夾中建立 themeReducer.js,並輸入:
const initialState = {
darkTheme: false
}
const reducer = (state = initialState, action) => {
switch(action.type) {
case 'CHANGE_THEME':
return {
...state,
darkTheme: !state.darkTheme
}
default:
return state
}
}
export default reducer;
reducer 是一個 function ,當 action 被 dispatch 時會發動,第一個參數是 state ,一般上會習慣給他初始值,第二個參數則是 action ,reducer 一般會搭配 switch ,根據不同的 action type 對 state 做操作,我們的範例中只有一個 action type ,所以只需要針對一個 case 做定義,default 值則是在沒有對應 case 時會回傳原有的 state。
特別注意的是一般我們不會直接改變 state 的值,而是重新創建一個 state 物件,以避免不可預期的 bug。
因此才會寫成
return {
...state,
darkTheme: !state.darkTheme
}
將目前的 state 的值加進新的物件,並針對要改變的部分改動,最後回傳新的物件當作新的 state
再來是 store 的部分,在 store 資料夾創建 configurestore.js:
import { createStore } from 'redux';
import themeReducer from '../reducers/themeReducer';
export default () => {
const store = createStore(
themeReducer
)
return store;
}
這邊非常簡單,從redux 中引入 createStore,並把剛剛創建的 reducer 傳入就可以了
(如果需要傳入多個 reducer 可以使用 applyMiddleware,就交給讀者自行探索了)
最後的最後,回到 react 的最父層 index.js,並改成:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import configureStore from './store/configureStore';
import { Provider } from 'react-redux';
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
serviceWorker.unregister();
這邊先呼叫剛剛的 configureStore function 建立 store 實體,而要能夠使用 store 中的 state 的元件都必須被包在 react-redux 引入的 Provider 中,包起來後再把 store 實體傳入,我們就做好使用 global state 的準備了。
今天的篇幅比我想像的還要長,因此在 component 中的應用就留到明天了,明天將會介紹使用 redux 的方式,偷偷透露一個好消息,現在使用 redux 的 state 也有 hooks 可以使用囉,變得方便很多,明天見囉!
有考慮過把 action.type 'CHANGE_THEME'
變成一個常數管理嗎?像這樣子:
const CHANGE_THEME = 'CHANGE_THEME';
就不怕說有可能會在 action 和 reducer 之間打錯字 XD
平常會這樣做,因為想說只有一個 action 就沒有採用這個方法,但還是感謝提醒!
嘿嘿!只是疑惑會不會有不同派別 XD